﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Windows;
using System.Collections.ObjectModel;
using ARR.Entities;
using System.Windows.Input;
using ARR.UI.Models;
using ARR.Shared;
using ARR.UI.Commands;
using DDF.Entity;
using System.Globalization;
using System.Windows.Data;
using telerik = Telerik.Windows.Controls;
using System.IO;
using System.Xml;
using System.Windows.Markup;
using System.Windows.Controls;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Controls;
using ARR.UI.Views;

namespace ARR.UI.ViewModels
{
    public class ArticleMasterViewModel : WorkspaceViewModel
    {
        internal IArticleMasterModel model;
        private ICommand deleteCommand;
        private ICommand saveCommand;
        private ICommand selectionChangedCommand;
        private ICommand loadedCommand;
        private ICommand rowValidatingCommand;
        private Entities.Attribute selectedAttribute;
        private Entities.Category selectedCategory;
        private ICommand beginningEditCommand;
        private ICommand filterByCategoryCommand;
        private ICommand changeUomCommand;
        private ICommand theoreticalMarginsCommand;
        private bool isCheckedViewDeletedRR;
        private UnitOfMeasureConvertion selectedUomConvertion;
        private ICommand checkeDeletedRRCommand;


        public ArticleMasterViewModel(IArticleMasterModel model)
        {
            this.model = model;
            this.DisplayName = Labels.MaestroDeArticulos;
            this.IsCheckedViewDeletedRR = true;

            //this.SelectedCategory = model.Categories[1];
            //FilterByCategory();
        }


        public ICommand CheckeDeletedRRCommand
        {
            get
            {
                if (checkeDeletedRRCommand == null)
                {
                    checkeDeletedRRCommand = new RelayCommand(param => CheckIsDeletedRangeReview(param), c => !IsClosing);
                }
                return checkeDeletedRRCommand;
            }
        }

        public ICommand FilterByCategoryCommand
        {
            get
            {
                if (filterByCategoryCommand == null)
                {
                    filterByCategoryCommand = new RelayCommand(param => FilterByCategory(), c => !IsClosing);
                }
                return filterByCategoryCommand;
            }
        }

        public ICommand DeleteCommand
        {
            get
            {
                if (deleteCommand == null)
                {
                    deleteCommand = new RelayCommand(param => DeleteArticles(), param => SelectedArticles != null && SelectedArticles.Any());
                }
                return deleteCommand;
            }
        }

        public ICommand SaveCommand
        {
            get
            {
                if (saveCommand == null)
                {
                    saveCommand = new RelayCommand(param => SaveArticles());
                }
                return saveCommand;
            }
        }

        public ICommand SelectionChangedCommand
        {
            get
            {
                if (selectionChangedCommand == null)
                {
                    selectionChangedCommand = new RelayCommand(param => GetSelectedItems(param as IList));
                }
                return selectionChangedCommand;
            }
        }

        public ICommand LoadedCommand
        {
            get
            {
                if (loadedCommand == null)
                {
                    loadedCommand = new RelayCommand(param => CompleteGridColumns(param as telerik.GridViewColumnCollection));
                }
                return loadedCommand;
            }
        }

        public ICommand AddingNewRowCommand
        {
            get
            {
                if (rowValidatingCommand == null)
                {
                    rowValidatingCommand = new RelayCommand(e => OnAddingNewRow(e as GridViewAddingNewEventArgs));
                }
                return rowValidatingCommand;
            }
        }

        public ICommand BeginningEditCommand
        {
            get
            {
                if (beginningEditCommand == null)
                {
                    beginningEditCommand = new RelayCommand(e => OnBeginningEdit(e as GridViewBeginningEditRoutedEventArgs));
                }
                return beginningEditCommand;
            }
        }

        public ICommand ChangeUomCommand
        {
            get
            {
                if (changeUomCommand == null)
                {
                    changeUomCommand = new RelayCommand(e => OpenChangeUomPopup());
                }
                return changeUomCommand;
            }
        }

        public ICommand TheoreticalMarginsCommand
        {
            get
            {
                if (theoreticalMarginsCommand == null)
                {
                    theoreticalMarginsCommand = new RelayCommand(param => OpenTheoreticalMarginsPopup());
                }
                return theoreticalMarginsCommand;
            }
        }

        public ObservableCollection<Article> Articles
        {
            get
            {
                //DB: El check de Ver deleted RR dejo de funcionar con la ultima modificacion. Vuelvo a dejarlo como estaba, ya que no entiendo el comentario de abajo. REVISAR con Lucas.
                //Si está chequeado mostrar todo muestro todo. Si no muestro los que no estén Deleted RR y los que estén Deleted y estén clasificados como New o Delisted
                //return new ObservableCollection<Article>(model.Articles.Where(x => IsCheckedViewDeletedRR || (!x.IsDeletedRangeReview || (x.IsDeletedRangeReview && (x.IsNew || x.IsDelisted))))
                     return new ObservableCollection<Article>(model.Articles.Where(x => x.IsDeletedRangeReview == false || IsCheckedViewDeletedRR)
                                                                       .OrderBy(x => x.RankingSort));
            }
        }

        public ObservableCollection<AttributeType> AttributeTypes
        {
            get
            {
                return new ObservableCollection<AttributeType>(model.AttributeTypes.Where(x => !x.IsArticleBaseColumn));
            }
        }

        public ObservableCollection<PlanogramLocation> PlanogramLocations
        {
            get
            {
                return new ObservableCollection<PlanogramLocation>(model.PlanogramLocations);
            }
        }

        public ObservableCollection<AttributeType> ArticleAttributeTypes
        {
            get
            {
                return new ObservableCollection<AttributeType>(model.AttributeTypes.Where(x => x.IsArticleBaseColumn));
            }
        }

        public ObservableCollection<RangeReview> RangeReviews
        {
            get
            {
                return new ObservableCollection<RangeReview>(model.RangeReviews);
            }
        }

        public ObservableCollection<Category> Categories
        {
            get
            {
                return new ObservableCollection<Category>(model.Categories);
            }
        }

        public ObservableCollection<Category> CategoriesWithAllOption
        {
            get
            {
                var cats = model.Categories.OrderBy(x => x.Code).ToList();
                cats.Insert(0, new Category { Id = 0, Code = "000000", Name = "TODAS" });
                return new ObservableCollection<Category>(cats);
            }
        }
        

        public ObservableCollection<Category> SubCategories
        {
            get
            {
                return new ObservableCollection<Category>(model.SubCategories);
            }
        }

        public ObservableCollection<Comment> Comments
        {
            get
            {
                return new ObservableCollection<Comment>(model.Comments);
            }
        }

        public ObservableCollection<UnitOfMeasureConvertion> UomConvertions
        {
            get
            {
                return new ObservableCollection<UnitOfMeasureConvertion>(model.UomConvertions);
            }
        }

        public UnitOfMeasureConvertion SelectedUomConvertion
        {
            get
            {
                return selectedUomConvertion;
            }
            set
            {
                var selecteds = Articles.Where(x => x.IsSelected);

                if (selecteds.Any())
                {
                    if (selecteds.Select(x => x.UOM).Distinct().Count() == 1)
                    {
                        if (selecteds.First().UOM == value.SourceUnit)
                        {
                            foreach (var art in selecteds)
                            {
                                art.UnitOfMeasureConvertionId = value.Id;
                                art.UomConversion = value;
                            }


                            selectedUomConvertion = null;

                            SaveArticles();
                            OnPropertyChanged<ArticleMasterViewModel>(vm => vm.Articles);
                            OnPropertyChanged<ArticleMasterViewModel>(vm => vm.SelectedUomConvertion);
                        }
                        else
                        {
                            (new Alert("La UOM origen de la conversión seleccionada no coincide con la de los artículos elegidos.", Labels.Advertencia, AlertType.Warning)).ShowDialog();
                        }
                    }
                    else
                    {
                        (new Alert("Los artículos seleccionados deben tener la misma UOM", Labels.Advertencia, AlertType.Warning)).ShowDialog();
                    }
                }
                else
                {
                    (new Alert("Debe seleccionar articulos para poder cambiarles la UOM.", Labels.Advertencia, AlertType.Warning)).ShowDialog();
                }
            }
        }

        public List<Article> SelectedArticles { get; set; }

        public Article CurrentArticle { get; set; }

        public Category SelectedCategory { get; set; }

        public Entities.Attribute SelectedAttribute
        {
            get
            {
                return selectedAttribute;
            }
            set
            {
                selectedAttribute = value;

                if (selectedAttribute != null)
                {
                    int id = this.selectedAttribute.Id;
                    int newAttributetypeId = this.selectedAttribute.AttributeTypeId;

                    if (CurrentArticle.Attributes == null)
                        CurrentArticle.Attributes = new List<Entities.Attribute>();

                    if (!CurrentArticle.Attributes.Any(a => a.Id == id))
                    {
                        //Elimino cualquier otro atributo que sea del mismo tipo.
                        var toRemove = from att in CurrentArticle.Attributes
                                       where att.AttributeTypeId == newAttributetypeId
                                       select att.Id;

                        CurrentArticle.Attributes.RemoveAll(att => toRemove.Contains(att.Id));

                        //Agrego el nuevo seleccionado
                        CurrentArticle.Attributes.Add(selectedAttribute);
                    }
                }
            }
        }
        
        public bool IsCheckedViewDeletedRR
        {
            get { return isCheckedViewDeletedRR; }
            set
            {
                isCheckedViewDeletedRR = value;

                OnPropertyChanged<ArticleMasterViewModel>(vm => vm.Articles);
            }
        }




        private void CheckIsDeletedRangeReview(object articleId)
        {
            if (articleId != null)
            {
                int id = (int)articleId;
                var article = Articles.SingleOrDefault(x => x.Id == id);

                if (article != null)
                {
                    article.IsDeletedRangeReview = true;
                }

                OnPropertyChanged<ArticleMasterViewModel>(vm => vm.Articles);
            }
        }
        
        public void FilterByCategory()
        {
            if (SelectedCategory != null)
            {
                model.LoadArticles(SelectedCategory.Id);
                model.LoadSubCategories(SelectedCategory.Id);

                OnPropertyChanged<ArticleMasterViewModel>(vm => vm.Articles);
                OnPropertyChanged<ArticleMasterViewModel>(vm => vm.SubCategories);
            }
        }

        private void OpenChangeUomPopup()
        {
            var selecteds = Articles.Where(x => x.IsSelected);

            if (selecteds.Any())
            {
                if (selecteds.Select(x => x.UOM).Distinct().Count() == 1)
                {
                    ArticleMasterChangeUomPopupViewModel vm = new ArticleMasterChangeUomPopupViewModel(ModelFactory.GetInstance<IArticleMasterChangeUomPopupModel>(selecteds.ToList()));
                    ArticleMasterChangeUomPopupView popup = new ArticleMasterChangeUomPopupView();
                    popup.DataContext = vm;

                    bool? res = popup.ShowDialog();

                    if (res.HasValue && res.Value)
                    {
                        FilterByCategory();
                    }
                }
                else
                {
                    (new Alert("Los artículos seleccionados deben tener la misma UOM", Labels.Advertencia, AlertType.Warning)).ShowDialog();
                }
            }
            else
            {
                (new Alert("Debe seleccionar articulos para poder cambiarles la UOM.", Labels.Advertencia, AlertType.Warning)).ShowDialog();
            }
        }

        private void GetSelectedItems(IList selectedItems)
        {
            IEnumerable<Article> stores = (selectedItems.Cast<Article>());
            SelectedArticles = stores.ToList();
        }

        private void OnAddingNewRow(GridViewAddingNewEventArgs e)
        {
            Article newArticle = new Article();

            model.Articles.Add(newArticle);
            e.NewObject = newArticle;
        }

        private void OnBeginningEdit(GridViewBeginningEditRoutedEventArgs e)
        {
            CurrentArticle = e.Row.Item as Article;
        }

        private void DeleteArticles()
        {
            model.DeleteArticles(SelectedArticles);
            OnPropertyChanged<ArticleMasterViewModel>(vm => vm.Articles);
        }

        private void SaveArticles()
        {
            if (CanSave())
            {
                //Guardo los cambios
                model.Save();

                //Recargo el pareto
                FilterByCategory();

                OnPropertyChanged<ArticleMasterViewModel>(vm => vm.Articles);
            }
        }

        private void CompleteGridColumns(telerik.GridViewColumnCollection columns)
        {
            //Completo primero columnas de fechas
            for (int i = 0; i < WorkspaceData.Instance.RangeReview.TotalMonths; i++)
            {
                telerik.GridViewDataColumn col = new telerik.GridViewDataColumn { Header = WorkspaceData.Instance.RangeReview.FirstMonth.AddMonths(i).ToString("MMMM") };
                col.TextAlignment = TextAlignment.Right;
                col.CellTemplate = SalesByDateDataTemplate(WorkspaceData.Instance.RangeReview.FirstMonth.AddMonths(i));
                col.CellTemplate.Seal();
                columns.Add(col);
            }

            //Completo columnas de PlanogramLocations
            foreach (var location in model.PlanogramLocations)
            {
                telerik.GridViewDataColumn col = new telerik.GridViewDataColumn { Header = location.Name };
                col.TextAlignment = TextAlignment.Right;
                col.CellTemplate = SpacesByLocationDataTemplate(location.Name);
                col.CellTemplate.Seal();
                columns.Add(col);
            }

            //Despues columnas de atributos dinámicos
            if (AttributeTypes != null)
            {
                foreach (AttributeType type in AttributeTypes.OrderBy(x => x.Id))
                {
                    telerik.GridViewDataColumn col = new telerik.GridViewDataColumn { Header = type.Name };
                    col.Tag = "Attribute|" + type.Name + "|" + type.Id;
                    col.UniqueName = "AttributeColumn";
                    col.DataType = typeof(string);
                    Binding binding = new Binding("Attributes");
                    binding.Converter = new Helpers.AttributeConverter();
                    binding.ConverterParameter = type.Id;
                    binding.ValidatesOnDataErrors = true;
                    binding.ValidatesOnExceptions = false;
                    binding.NotifyOnValidationError = false;
                    col.DataMemberBinding = binding;

                    DataTemplate editTemplate = new DataTemplate();
                    FrameworkElementFactory combo = new FrameworkElementFactory(typeof(telerik.RadComboBox));
                    editTemplate.VisualTree = combo;
                    combo.SetValue(telerik.RadComboBox.ClearSelectionButtonVisibilityProperty, Visibility.Visible);
                    combo.SetValue(telerik.RadComboBox.ClearSelectionButtonContentProperty, "Falta Completar");
                    combo.SetValue(telerik.RadComboBox.ItemsSourceProperty, type.Values);
                    combo.SetValue(telerik.RadComboBox.SelectedValuePathProperty, "Id");
                    combo.SetValue(telerik.RadComboBox.DisplayMemberPathProperty, "AttributeValue");

                    //Binding bindingSelectedValue = new Binding("Attributes");
                    //bindingSelectedValue.Converter = new Helpers.AttributeConverterId();
                    //bindingSelectedValue.ConverterParameter = type.Id;
                    //bindingSelectedValue.ValidatesOnDataErrors = true;
                    //bindingSelectedValue.ValidatesOnExceptions = false;
                    //bindingSelectedValue.NotifyOnValidationError = false;
                    //combo.SetBinding(telerik.RadComboBox.SelectedItemProperty, bindingSelectedValue);

                    //Binding BindingSelectedItem = new Binding();
                    //BindingSelectedItem.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(UserControl), 1);
                    //BindingSelectedItem.Path = new PropertyPath("DataContext.SelectedAttribute");
                    //combo.SetBinding(telerik.RadComboBox.SelectedItemProperty, BindingSelectedItem);
                    editTemplate.Seal();

                    col.CellEditTemplate = editTemplate;

                    columns.Add(col);
                }
            }
        }

//        private DataTemplate AttributeDataTemplate(int id)
//        {
//            DataTemplate attributeTemplate = new DataTemplate();
//            string xaml = @"<DataTemplate x:Name='AttributeColumnTemplate'
//                            xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
//                            xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>";
//            xaml += "<TextBlock x:Name='AttributeTextBlock' DataContext='{Binding Attributes, ValidatesOnDataErrors=true, ValidatesOnExceptions=False, NotifyOnValidationError=False, Converter={StaticResource attributeConverter}, ConverterParameter=" + id + "}' Text='{Binding AttributeValue}' /></DataTemplate>";

//            StringReader sr = new StringReader(xaml);
//            XmlReader reader = XmlReader.Create(sr);
//            attributeTemplate = (DataTemplate)XamlReader.Load(reader);
//            return attributeTemplate;
//        }

        private DataTemplate SalesByDateDataTemplate(DateTime date)
        {
            DataTemplate salesByDateTemplate = new DataTemplate();
            string xaml = @"<DataTemplate x:Name='SalesByDateDataTemplate'
                            xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                            xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>";
            xaml += "<TextBlock TextAlignment='Right' DataContext='{Binding SalesByDate, Converter={StaticResource salesByDateConverter}, ConverterParameter=" + date + "}' Text='{Binding Value}' /></DataTemplate>";

            StringReader sr = new StringReader(xaml);
            XmlReader reader = XmlReader.Create(sr);
            salesByDateTemplate = (DataTemplate)XamlReader.Load(reader);
            return salesByDateTemplate;
        }

        private DataTemplate SpacesByLocationDataTemplate(string location)
        {
            DataTemplate spacesByLocationTemplate = new DataTemplate();
            string xaml = @"<DataTemplate x:Name='SpacesByLocationDataTemplate'
                            xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                            xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>";
            xaml += "<TextBlock TextAlignment='Right' DataContext='{Binding SpacesByLocation, Converter={StaticResource spacesByLocationConverter}, ConverterParameter=" + location + "}' Text='{Binding Value}' /></DataTemplate>";

            StringReader sr = new StringReader(xaml);
            XmlReader reader = XmlReader.Create(sr);
            spacesByLocationTemplate = (DataTemplate)XamlReader.Load(reader);
            return spacesByLocationTemplate;
        }

        private bool CanSave()
        {
            List<Article> toBeSaved = Articles.Where(art => art.GetEntityState() != EntityState.Original).ToList();

            if (toBeSaved.Any())
            {
                return !toBeSaved.Any(a => !a.IsValid);
            }

            return false;
        }

        private void OpenTheoreticalMarginsPopup()
        {
            var selecteds = Articles.Where(x => x.IsSelected).Select(x => x.Id).Distinct();

            if (!selecteds.Any())
            {
                (new Alert(Messages.MargenTeoricoArticulosSeleccionados, Labels.Advertencia, AlertType.Warning)).ShowDialog();
            }
            else
            {
                TheoreticalMarginsViewModel vm = new TheoreticalMarginsViewModel(selecteds, false);
                TheoreticalMarginsPopupView popup = new TheoreticalMarginsPopupView();
                popup.DataContext = vm;


                bool? result = popup.ShowDialog();

                if (result.HasValue && result.Value)
                {
                    FilterByCategory();
                }
            }
        }
    }

}
